package edu.cmich.cps.cps240.partyprincesspalace.hw06;

import java.io.*;
import java.util.Vector;

/**
 * 
 * @author holde1ja
 */
public class CreateHDLFile {
	private File output;
	private BufferedWriter writeOut;
	
	/**
	 * Initialises the CreateHDLFile object for writing
	 * @param out The file we will try to write to
	 * @throws IOException If there is a problem opening the file for writing
	 */
	public CreateHDLFile(File out) throws IOException{
		output = out;
		writeOut = new BufferedWriter (new FileWriter(output));
	}
	
	/**
	 * Passes parameters into another method which does the real work, and then takes all of his hard work
	 * and writes it out to file.  All the while, stealing credit for itself.
	 * @param input All of the inputs into the circuit.
	 * @param output All of the outputs of the circuit.
	 * @param chips All of the chips in the circuit.
	 * @param wires The wire data in the circuit.  Not actually used, but put here for completeness
	 * @throws IOException If there was a problem writing out to file.
	 */
	public void create(Vector<InputBus> input, Vector<OutputBus> output, Vector<Chip> chips, Vector<Wire> wires) throws IOException{
		Vector<String> lines = getHDL(input, output, chips, wires);
		
		for (String line : lines)
		{
			writeOut.write(line);
			writeOut.newLine();
		}
		
		writeOut.close();
	}
	
	/**
	 * Generates a Vector<String> object, where each element is a line of
	 * HDL code.  The entire Vector can be written to a file in order to make
	 * a valid HDL file which represents our circuit 
	 * @param inputs The Inputs to our circuit 
	 * @param outputs the outputs from our circuit
	 * @param chips All of the component pieces of our circuit
	 * @param wires Shouldn't be needed, but they are here just in case 
	 * 				ChipPin.getPartner().getName() doesn't work
	 * @return A Vector<String> where each string is a line of HDL code in proper order
	 */
	public Vector<String> getHDL(Vector<InputBus> inputs, Vector<OutputBus> outputs, Vector<Chip> chips, Vector<Wire> wires)
	{
		//TODO: ERROR TRAPPING, what if our inputs/outputs/chips/wires are empty, or null?
		Vector<String> ret = new Vector<String>();
		String build = "";
		//TODO: Determining the name of the circuit!
		ret.add("CHIP circuit {");
		
		build += "IN ";
		//TODO: Need cleaner way of grabbing vector of internal input/output pins
		for (InputBus input : inputs)
		{
			//TODO: Need InputBus to generate it's own HDL code
			//until then, we'll just grab the name
			build += input.getName() + ", ";
		}
		//The last element tacked on an extra two characters to the end
		build = build.substring(0, build.lastIndexOf(',')) + ";";
		
		ret.add(build);
		build = "";
		
		build += "OUT ";
		for (OutputBus output: outputs)
		{
			build += output.getName() + ", ";
		}
		build = build.substring(0, build.lastIndexOf(',')) + ";";
		ret.add(build);
		build = "";
		
		ret.add("PARTS:");
		
		for (Chip chip : chips)
		{
			build = chip.getName();
			build += "(";
			for (ChipPin in : chip.inputs)
			{
				if (in.getPartner() == null)
				{
					throw new IllegalArgumentException("Can not continue, a chip has an empty input");
				}
				build += in.getName() + "=" + in.getPartner().getParent().getName() + ", ";
			}
			
			for (ChipPin out : chip.outputs)
			{
				if (out.getPartner() == null)
				{
					//If the output is discarded, leave it empty
					continue;
				}
				build += out.getName() + "=" + out.getPartner().getParent().getName() + ", ";
			}
			
			//We should have an extra ", " on the end of the string
			build = build.substring(0, build.lastIndexOf(',')) + ");";
			
			ret.add(build);
		}
		
		ret.add("}");
		return ret;
	}

}
